using Devil;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace GameToolkit.Editor
{
    [CustomPropertyDrawer(typeof(UIDAttribute))]
    public class UIDDrawer : PropertyDrawer
    {

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            if (property.propertyType != SerializedPropertyType.Integer)
                return 40;
            return base.GetPropertyHeight(property, label);
        }

        bool ResetDifferentValues(SerializedProperty property, ref int newValue)
        {
            if (property.serializedObject.isEditingMultipleObjects)
            {
                var seris = property.serializedObject.targetObjects;
                foreach (var ser in seris)
                {
                    var p = new SerializedObject(ser);
                    p.FindProperty(property.propertyPath).intValue = GlobalUtil.GenUniqueID();
                    p.ApplyModifiedProperties();
                    p.Dispose();
                }
                GUI.changed = true;
                return true;
            }
            else
            {
                newValue = GlobalUtil.GenUniqueID();
                return false;
            }
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (property.propertyType != SerializedPropertyType.Integer)
            {
                EditorGUI.HelpBox(position, "UIDAttribute Only Support Integer Type", MessageType.Warning);
                return;
            }
            var att = attribute as UIDAttribute;
            EditorGUI.BeginProperty(position, label, property);
            var lv = EditorGUI.indentLevel;
            var vpos = EditorGUI.PrefixLabel(position, label);
            EditorGUI.indentLevel = 0;
            int newValue = property.intValue;
            bool setNewValue = false;
            if (property.intValue == 0 && !att.EnableZero && !property.hasMultipleDifferentValues)
            {
                //newValue = GlobalUtil.GenUniqueID();
                setNewValue |= !ResetDifferentValues(property, ref newValue);
            }
            var w = att.EnableUpdate ? Mathf.Min(60, vpos.width * 0.5f) : 0;
            vpos.width -= w;
            var cname = ParallelUtils.Concat(property.serializedObject.targetObject.GetInstanceID(), '_', property.propertyPath);
            GUI.SetNextControlName(cname);
            if (property.hasMultipleDifferentValues)
                EditorGUI.LabelField(vpos, "[different values]", DevilEditorUtility.HintStyle("label"));
            else if (att.Hex)
                DevilEditorUtility.Hint(vpos, property.intValue.ToString("x"));
            else
                DevilEditorUtility.Hint(vpos, property.intValue.ToString());

            if (att.EnableZero && att.EnableUpdate)
            {
                w *= 0.5f;
                if (GUI.Button(new Rect(vpos.xMax, vpos.y, w, vpos.height), "0", "minibuttonleft"))
                {
                    setNewValue = true;
                    newValue = 0;
                }
                if (GUI.Button(new Rect(vpos.xMax + w, vpos.y, w, vpos.height), "X", "minibuttonright"))
                { //newValue = GlobalUtil.GenUniqueID();
                    setNewValue |= !ResetDifferentValues(property, ref newValue);
                }
            }
            else if (att.EnableUpdate)
            {
                label.text = "Reset";
                if (GUI.Button(new Rect(vpos.xMax, vpos.y, w, vpos.height), label))
                {  //newValue = GlobalUtil.GenUniqueID();
                    setNewValue |= !ResetDifferentValues(property, ref newValue);
                }
            }
            else if (att.EnableZero)
            {
                label.text = "Zero";
                if (GUI.Button(new Rect(vpos.xMax, vpos.y, w, vpos.height), label))
                {
                    setNewValue = true;
                    newValue = 0;
                }
            }

            if (Event.current.type == EventType.ExecuteCommand /*&& GUI.GetNameOfFocusedControl() */)
            {
                if (Event.current.commandName == "Paste" && GUI.GetNameOfFocusedControl() == cname)
                {
                    var txt = GUIUtility.systemCopyBuffer.Trim();
                    int v;
                    System.Globalization.NumberStyles style;
                    if (Regex.IsMatch(txt, "^[a-fA-F0-9]+$"))
                        style = System.Globalization.NumberStyles.HexNumber;
                    else if (Regex.IsMatch(txt, "^[0-9]+$"))
                        style = System.Globalization.NumberStyles.Integer;
                    else
                        style = System.Globalization.NumberStyles.Any;
                    if (int.TryParse(txt, style, null, out v))
                    {
                        setNewValue = true;
                        newValue = v;
                    }
                    Event.current.Use();
                }
            }

            if (setNewValue && (newValue != property.intValue || property.hasMultipleDifferentValues))
            {
                property.intValue = newValue;
                GUI.changed = true;
                GUI.FocusControl(null);
            }
            EditorGUI.indentLevel = lv;
            EditorGUI.EndProperty();

        }
    }
}